package com.ido.otaclient.home;

import android.text.TextUtils;
import android.util.Log;


import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ido.otaclient.R;
import com.ido.otaclient.Status;
import com.ido.otaclient.StatusUpgrade;
import com.ido.otaclient.StatusUpgradeTask;
import com.ido.otaclient.UploadConfigPreference;
import com.ido.otaclient.api.OkhttpUtil;
import com.ido.otaclient.base.ApiConstant;
import com.ido.otaclient.base.Constant;
import com.ido.otaclient.base.IDLog;
import com.ido.otaclient.dialog.WaitingDialog;
import com.ido.otaclient.font.FontConfig;
import com.ido.otaclient.font.FontPerfence;
import com.ido.otaclient.fontb.FontBConfig;
import com.ido.otaclient.fontb.FontBPerference;
import com.ido.otaclient.four.FourToOneConfig;
import com.ido.otaclient.four.FourToOnePreference;
import com.ido.otaclient.module.Device;
import com.ido.otaclient.module.DeviceProgressEntity;
import com.ido.otaclient.module.UploadConfig;
import com.ido.otaclient.module.Veneer;
import com.ido.otaclient.nordic.NordicConfig;
import com.ido.otaclient.nordic.NordicConfigPerfence;
import com.ido.otaclient.realtk.RealtkConfig;
import com.ido.otaclient.realtk.RealtkConfigPerfence;
import com.ido.otaclient.three.ThreeToOneConfig;
import com.ido.otaclient.three.ThreeToOnePerfence;
import com.ido.otaclient.two.TwoToOneConfig;
import com.ido.otaclient.two.TwoToOnePerfence;
import com.ido.otaclient.util.AppExecutors;
import com.ido.otaclient.util.ResourceUtil;
import com.ido.otaclient.util.ToastUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * Copyright (c) 2019 深圳市爱都科技有限公司. All rights reserved.
 *
 * @Author: xyb
 * @CreateDate: 2020-02-24 11:52
 * @description
 */
public class HomePresenter implements HomeContract.Presenter{
    private static final String TAG = "HomePresenter";

    private HomeContract.View mView;

    /**
     * 扫描有效ip的次数
     */
    private int mCountVeneerScance;

    /**
     * 有效ip数量
     */
    private int mEffectCountVeneer;

    /**
     * 结束的次数
     */
    private int mStopVeneer;

    /**
     * 搜索到的设备列表
     */
    private List<Device> mDeviceList = new ArrayList<>();

    /**
     * 升级完成和无任务状态都为0 ，升级中为1 ，取消升级为2
     */
    private int mStatusUpgradeTask = 0;

    /**
     * 配置当前升级类型
     */
    private UploadConfigPreference mUploadConfigPrefence;

    /**
     * 任务名称
     */
    private String mTaskName;

    /**
     * nordic 的配置信息
     */
    private NordicConfig mNordicConfig;

    /**
     * 四合一配置
     */
    private FourToOneConfig mFourToOneConfig;

    /**
     * 二合一配置
     */
    private TwoToOneConfig mTwoToOneConfig;

    /**
     * 三合一配置
     */
    private ThreeToOneConfig mThreeToOneConfig;

    /**
     * font 配置
     */
    private FontConfig mFontConfig;

    /**
     * font b 配置
     */
    private FontBConfig mFontBConfig;

    /**
     * realtk 升级
     */
    private RealtkConfig mRealtkConfig;

    public HomePresenter(HomeContract.View mView) {
        this.mView = mView;
        mUploadConfigPrefence = UploadConfigPreference.getInstance();
    }

    @Override
    public void start() {

    }

    @Override
    public void release() {

    }

    @Override
    public void getConfigInfo() {

        UploadConfig uploadConfig = mUploadConfigPrefence.getUploadConfig();
        mView.showTaskName(false);
        mView.showUploadType(false);
        mView.showUploadPlatform(false);
        mView.showFirmwareNormal(false);
        mView.showBootloader(false);
        mView.showFirmwareSpecial(false);
        mView.showFirmwareFont(false);
        mView.showFirmwareNew(false);
        mView.showStartConfig(false);
        IDLog.d(TAG, "getConfigInfo: " + uploadConfig.toString());
        if(uploadConfig != null && !TextUtils.isEmpty(uploadConfig.getTaskName())){
            switch (uploadConfig.getTaskName()){
                case Constant.TASK_NAME_NORDIC:
                    NordicConfigPerfence nordicConfigPerfence = NordicConfigPerfence.getInstance();
                    mNordicConfig = nordicConfigPerfence.getNordicConfig();
                    mView.showTaskName(true);
                    mView.setTaskName(ResourceUtil.getString(R.string.upload_type_nordic));
                    //显示升级平台
                    mView.showUploadPlatform(true);
                    mView.setUploadPlatform(Constant.PLATFORM_NAME_NORDIC);
                    mView.setDeviceId(mNordicConfig.getDeviceId());
                    mView.showUploadType(true);
                    mView.setUploadName(mNordicConfig.getUploadName());
                    mView.showFirmwareNormal(true);
                    mView.setFirmwareNameNormal(mNordicConfig.getFirewareNormalName());
                    mView.setFirmwareVersionNormal(mNordicConfig.getFirewareNormalVersion());
                    break;
                case Constant.TASK_NAME_FOUR_TO_ONE:
                    mView.showTaskName(true);
                    mView.setTaskName(ResourceUtil.getString(R.string.upload_type_four_to_one));
                    mView.showBootloader(true);
                    mView.showFirmwareSpecial(true);
                    mView.showFirmwareFont(true);
                    mView.showFirmwareNew(true);

                    FourToOnePreference fourToOnePreference = FourToOnePreference.getInstance();
                    mFourToOneConfig = fourToOnePreference.getUploadConfig();
                    mView.setBootloaderName(mFourToOneConfig.getBootloaderName());
                    mView.setBootloaderVersion(mFourToOneConfig.getBootloaderVersion());
                    mView.setFirmwareNameSpecial(mFourToOneConfig.getFirewareSpecialName());
                    mView.setFirmwareVersionSpecial(mFourToOneConfig.getFirewareSpecialVersion());
                    mView.setFirmwareNameFont(mFourToOneConfig.getFontName());
                    mView.setFirmwareVersionFont(mFourToOneConfig.getFontVersion());
                    mView.setFirmwareNameNew(mFourToOneConfig.getFirewareNewName());
                    mView.setFirmwareFontVersionNew(mFourToOneConfig.getFirewareNewVersion());
                    mView.setDeviceId(mFourToOneConfig.getDeviceId());
                    break;
                case Constant.TASK_NAME_TWO_TO_ONE:
                    mView.showTaskName(true);
                    mView.setTaskName(ResourceUtil.getString(R.string.upload_type_two_to_one));
                    mView.showBootloader(true);
                    mView.showFirmwareNew(true);
                    mView.showUploadPlatform(true);

                    TwoToOnePerfence twoToOnePerfence = TwoToOnePerfence.getInstance();
                    mTwoToOneConfig = twoToOnePerfence.getTwoToOneConfig();
                    mView.setBootloaderName(mTwoToOneConfig.getBootloaderName());
                    mView.setBootloaderVersion(mTwoToOneConfig.getBootloaderVersion());
                    mView.setFirmwareNameNew(mTwoToOneConfig.getFirewareNewName());
                    mView.setFirmwareFontVersionNew(mTwoToOneConfig.getFirewareNewVersion());
                    mView.setUploadPlatform(mTwoToOneConfig.getUploadPlatform());
                    mView.setDeviceId(mTwoToOneConfig.getDeviceId());
                    break;
                case Constant.TASK_NAME_THREE_TO_ONE:
                    mView.showTaskName(true);
                    mView.setTaskName(ResourceUtil.getString(R.string.upload_type_three_to_one));
                    mView.showFirmwareSpecial(true);
                    mView.showFirmwareFont(true);
                    mView.showFirmwareNew(true);
                    mView.showUploadPlatform(true);

                    ThreeToOnePerfence threeToOnePerfence = ThreeToOnePerfence.getInstance();
                    mThreeToOneConfig = threeToOnePerfence.getThreeToOneConfig();
                    Log.d(TAG, "getConfigInfo: " + mThreeToOneConfig.toString());
                    mView.setFirmwareNameSpecial(mThreeToOneConfig.getFirewareSpecialName());
                    mView.setFirmwareVersionSpecial(mThreeToOneConfig.getFirewareSpecialVersion());
                    mView.setFirmwareNameFont(mThreeToOneConfig.getFontName());
                    mView.setFirmwareVersionFont(mThreeToOneConfig.getFontVersion());
                    mView.setFirmwareNameNew(mThreeToOneConfig.getFirewareNewName());
                    mView.setFirmwareFontVersionNew(mThreeToOneConfig.getFirewareNewVersion());
                    mView.setUploadPlatform(mThreeToOneConfig.getUploadPlatform());
                    mView.setDeviceId(mThreeToOneConfig.getDeviceId());
                    break;
                case Constant.TASK_NAME_FONT:
                    mView.showTaskName(true);
                    mView.setTaskName(ResourceUtil.getString(R.string.upload_type_B));
                    mView.showFirmwareFont(true);
                    mView.showFirmwareNew(true);

                    FontPerfence fontPerfence = FontPerfence.getInstance();
                    mFontConfig = fontPerfence.getFontConfig();
                    mView.setFirmwareNameFont(mFontConfig.getFontName());
                    mView.setFirmwareVersionFont(mFontConfig.getFontVersion());
                    mView.setFirmwareNameNew(mFontConfig.getFirewareNewName());
                    mView.setFirmwareFontVersionNew(mFontConfig.getFirewareNewVersion());
                    mView.setDeviceId(mFontConfig.getDeviceId());
                    break;
                case Constant.TASK_NAME_FONT_B:
                    mView.showTaskName(true);
                    mView.setTaskName(ResourceUtil.getString(R.string.upload_type_B_FONT));
                    mView.showFirmwareFont(true);
                    mView.showFirmwareNew(true);
                    mView.showBootloader(true);

                    FontBPerference fontBPerference = FontBPerference.getInstance();
                    mFontBConfig = fontBPerference.getFontBConfig();

                    mView.setBootloaderName(mFontBConfig.getBootloaderName());
                    mView.setBootloaderVersion(mFontBConfig.getBootloaderVersion());
                    mView.setFirmwareNameFont(mFontBConfig.getFontName());
                    mView.setFirmwareVersionFont(mFontBConfig.getFontVersion());
                    mView.setFirmwareNameNew(mFontBConfig.getFirewareNewName());
                    mView.setFirmwareFontVersionNew(mFontBConfig.getFirewareNewVersion());
                    mView.setDeviceId(mFontBConfig.getDeviceId());
                    break;
                case Constant.TASK_NAME_REALTK:
                    mView.showTaskName(true);
                    mView.setTaskName(ResourceUtil.getString(R.string.upload_type_realtk));
                    mView.showFirmwareNew(true);

                    RealtkConfigPerfence realtkConfigPerfence = RealtkConfigPerfence.getInstance();
                    mRealtkConfig = realtkConfigPerfence.getRealtkConfig();

                    mView.setFirmwareNameNew(mRealtkConfig.getFirewareNormalName());
                    mView.setFirmwareFontVersionNew(mRealtkConfig.getFirewareNormalVersion());
                    mView.setDeviceId(mRealtkConfig.getDeviceId());
                    break;
            }
        }else {
           mView.showStartConfig(true);
        }
    }


    @Override
    public void toStartTask(List<Veneer> veneerList,String taskName) {
        mTaskName = taskName;
        getDeviceListByIp(veneerList);
    }


    /**
     * 结束任务
     */
    @Override
    public void stopTask(List<Veneer> veneerList) {
        mStopVeneer = 0;
        for (int i = 0; i < veneerList.size(); i++) {
            String ip = veneerList.get(i).getIp();
            //正在升级中的ip
            int status = veneerList.get(i).getUpdateStatus();
            if (TextUtils.isEmpty(ip)) {
                return;
            }
            //向升级中的单板发送取消命令
            if(status == StatusUpgrade.UPGRADE.getCode()){
                String url = ApiConstant.URL_HEAD + veneerList.get(i).getIpPort() +"/"+ ApiConstant.METHOD_TASK_STOP;
                
                OkhttpUtil okhttpUtil = OkhttpUtil.getInstance();
                okhttpUtil.getSyn(url, new OkhttpUtil.OkhttpCallback() {
                    @Override
                    public void onSuccess(String success) {
                        AppExecutors.globalAppExecutors().mainThread().execute(() -> stopStatus(success));
                    }

                    @Override
                    public void onFailed(String message) {
                        AppExecutors.globalAppExecutors().mainThread().execute(() -> updateStopVeneer(message));
                    }
                });
            }
        }
    }

    /**
     * 设置
     * @param message
     */
    private void updateStopVeneer(String message) {
        mStopVeneer++;
        updateVeneer(message);
        //所有的单板都停止之后才能开始下一次升级
        if(mStopVeneer >= Integer.parseInt(mView.getUpgrageCount())){
            mView.setTextBtnStartTask(ResourceUtil.getString(R.string.task_start));
            mView.showProgress(false);
            mView.stopTimer();
            //更新设备信息
            showDeviceList(mView.getDeviceList());
            /**
             * 所有在升级中的设备都取消升级了
             */
            mStatusUpgradeTask = StatusUpgradeTask.CANCEL.getCode();
        }
    }

    @Override
    public void searchTask(List<Veneer> veneerList, List<Device> deviceList) {
        //给升级成功的手环发送亮屏
        int deviceCount = 0;
        /**
         * 升级成功的设备
         */
        List<Device> deviceListComplete = new ArrayList<>();
        for(int i = 0;i < deviceList.size();i++){
            Device device = deviceList.get(i);
            if(device.getUpdateStatus() == StatusUpgrade.COMPLETE.getCode()){
                deviceListComplete.add(device);
                deviceCount++;
            }
        }

        int veneerCount = 0;
        List<Veneer> veneerEffects = new ArrayList<>();
        for(int i = 0; i < veneerList.size();i++){
            Veneer veneer = veneerList.get(i);
            if(veneer.getUpdateStatus() == StatusUpgrade.WAITING.getCode()){
                veneerEffects.add(veneer);
                veneerCount++;
            }
        }

        if(veneerCount == 0)
            return;
        int divisor = deviceCount/veneerCount;
        int remainder = deviceCount%veneerCount;
        IDLog.d(TAG, "searchTask: " + "除数："+divisor + "余数,"+remainder +
                "有效设备数"+deviceCount + "有效单板数,"+veneerCount);

        for (int i = 0; i < veneerEffects.size(); i++) {
            String ip = veneerEffects.get(i).getIp();
                ip = ApiConstant.URL_HEAD + veneerEffects.get(i).getIpPort() + "/" + ApiConstant.METHOD_BRIGHT_SCREEN;

                StringBuffer sb = new StringBuffer();
                sb.append(ip);
                sb.append("?");
                sb.append("deviceList=");
                //除数为0 余数也为0
                if(divisor == 0 && remainder == 0){
                    return;
                } else if(divisor == 0 && remainder != 0){
                    //除数为0 余数不为0
                    if(i < remainder){
                        sb.append(deviceListComplete.get(i).getMac());
                    }
                } else if(divisor != 0 && remainder == 0){
                    //除数不为0 余数为0
                    for(int j = 0 ;j < divisor;j++){
                        if(j != 0){
                            sb.append(",");
                        }
                        sb.append(deviceListComplete.get(j+(i*divisor)).getMac());
                    }
                }else if(divisor != 0 && remainder != 0){
                    //除数不为0 余数都不为0
                    for(int j = 0 ;j < divisor;j++){
                        if(j != 0){
                            sb.append(",");
                        }
                        sb.append(deviceListComplete.get(j+(i*divisor)).getMac());
                    }
                    if(i < remainder){
                        sb.append(",");
                        sb.append(deviceListComplete.get((divisor*veneerCount)+i).getMac());
                    }

                }
                String url = sb.toString();
                IDLog.d(TAG, "searchTask: " + url);
                OkhttpUtil okhttpUtil = OkhttpUtil.getInstance();
                okhttpUtil.getSyn(url, new OkhttpUtil.OkhttpCallback() {
                    @Override
                    public void onSuccess(String success) {

                    }

                    @Override
                    public void onFailed(String message) {
                        //todo 是否有结束的设备
                        //IDLog.d(TAG, "onFailed: " + message);
                        //更新单板状态
                        updateVeneer(message);
                    }
                });
        }
    }

    @Override
    public void confirmConfig(boolean isConfig) {
        IDLog.d(TAG, "confirmConfig: "+ isConfig + ","+mStatusUpgradeTask);
        if(isConfig){
            //配置信息 1、升级完成 和取消升级
            if(StatusUpgradeTask.UPGRADE.getCode() == mStatusUpgradeTask){
                mView.setToConfig(isConfig,false);
            }else {
                mView.setToConfig(isConfig,true);
            }

        }else {
            //开始任务
            if(mStatusUpgradeTask == StatusUpgradeTask.UPGRADE.getCode()){
                //取消升级
                mView.showConfirmCancelTask();
            }else {
                mView.setToConfig(isConfig,true);
            }
        }
    }

    /**
     * 暂停状态
     * @param success
     */
    private void stopStatus(String success) {
        IDLog.d(TAG, "stopStatus: " + success);
        mStopVeneer++;
       //更新设备的状态
       List<Device> deviceList = mView.getDeviceList();
       List<Device> deviceListTemp = new ArrayList<>();
       //更新单板ip的状态
        List<Veneer> veneerList = mView.getVeneerList();
        List<Veneer> veneerListTemp = new ArrayList<>();
        try {
            JSONObject jsonObject = new JSONObject(success);
            String mac = jsonObject.getString("mac");
            String ip = jsonObject.getString("ip");
            String ipPort = jsonObject.getString("ipPort");

            //设置单板状态
            for(int j = 0 ;j < veneerList.size() ;j++){
                Veneer veneer = veneerList.get(j);
                if(veneer.getIpPort().equals(ipPort)){
                    veneer.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    veneer.setProgress(0);
                    veneerList.set(j,veneer);
                    veneerListTemp.addAll(veneerList);
                    mView.sendVeneerList(veneerListTemp);
                }
            }

            //设置设备状态
            for(int i = 0;i < deviceList.size();i++){
                Device device = deviceList.get(i);
                if(mac.equals(device.getMac())){
                    device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    deviceList.set(i,device);
                    deviceListTemp.addAll(deviceList);
                    mView.sendDeviceList(deviceListTemp);
                }
            }
            //所有的单板都停止之后才能开始下一次升级
            if(mStopVeneer >= Integer.parseInt(mView.getUpgrageCount())){
                mView.setTextBtnStartTask(ResourceUtil.getString(R.string.task_start));
                mView.showProgress(false);
                mView.stopTimer();
                //更新设备信息
                showDeviceList(mView.getDeviceList());
                /**
                 * 升级完成
                 */
                mStatusUpgradeTask = StatusUpgradeTask.CANCEL.getCode();
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void getVeneerStatus(List<Veneer> veneerList, List<Device> deviceList) {
        IDLog.d(TAG, "getVeneerStatus: ");
        OkhttpUtil okhttpUtil = OkhttpUtil.getInstance();
        for (int i = 0; i < veneerList.size(); i++) {
            String ipPort = veneerList.get(i).getIpPort();
            int status = veneerList.get(i).getUpdateStatus();
            if (TextUtils.isEmpty(ipPort)) {
                return;
            }
            //升级中的设备才查询状态
            if(status == StatusUpgrade.UPGRADE.getCode()){
                String url = ApiConstant.URL_HEAD + ipPort +"/"+ ApiConstant.METHOD_CHECK;
                Log.d(TAG, url + "");
                okhttpUtil.getSyn(url, new OkhttpUtil.OkhttpCallback() {
                    @Override
                    public void onSuccess(String success) {
                        AppExecutors.globalAppExecutors().mainThread().execute(()
                                -> showVeneerStatus(success));
                    }

                    @Override
                    public void onFailed(String message) {
                        //更新单板连接数
                        AppExecutors.globalAppExecutors().mainThread().execute(() -> updateVeneer(message));
                    }
                });
            }
        }
    }

    /**
     * 显示单板的状态
     * @param success
     */
    private void showVeneerStatus(String success) {
        IDLog.d(TAG, "showVeneerStatus: " + success);
        Gson gson = new Gson();
        DeviceProgressEntity deviceProgressEntity = gson.fromJson(success,DeviceProgressEntity.class);
        String ip = deviceProgressEntity.getIp();
        String mac = deviceProgressEntity.getMac();
        String ipPort = deviceProgressEntity.getIpPort();
        int progress = deviceProgressEntity.getProgress();
        int status = deviceProgressEntity.getStatus();
        List<Veneer> veneerList = mView.getVeneerList();
        List<Device> deviceList = mView.getDeviceList();
        List<Device> deviceListTemp = new ArrayList<>();
        List<Veneer> veneerListTemp = new ArrayList<>();
        for(int i = 0;i < veneerList.size();i++){
            //1、设置设备的状态  2、是否需要在发送一条指令检测是被是否真的升级成功
            Veneer veneer = veneerList.get(i);
            if(veneer.getIpPort().equals(ipPort)){
                if(status == StatusUpgrade.COMPLETE.getCode()){
                    IDLog.d(TAG, "showVeneerStatus: 成功" + success);
                    veneer.setProgress(0);
                    veneer.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    //找到对应的设备更新状态
                    for(int j = 0; j< deviceList.size();j++){
                        Device device = deviceList.get(j);
                        if(device.getMac().equals(mac)){
                            device.setUpdateStatus(StatusUpgrade.COMPLETE.getCode());
                            device.setIpPort("");
                            deviceList.set(j,device);
                            deviceListTemp.addAll(deviceList);
                            //设置本地的设备状态
                            mView.sendDeviceList(deviceListTemp);
                            //List<Veneer> veneerListTemp = new ArrayList<>();
                            veneerList.set(i,veneer);
                            veneerListTemp.addAll(veneerList);
                            mView.sendVeneerList(veneerListTemp);
                            showDeviceList(deviceList);
                            //一个单板结束后再分配任务
                            startTask(mView.getDeviceList(),mView.getVeneerList());
                        }
                    }
                }else if(status == StatusUpgrade.UPGRADE.getCode()){
                    IDLog.d(TAG, "showVeneerStatus: 升级中" + success);
                    for(int j = 0; j < deviceList.size();j++){
                        Device device = deviceList.get(j);
                        if(device.getMac().equals(mac)){
                            device.setUpdateStatus(StatusUpgrade.UPGRADE.getCode());
                            deviceList.set(j,device);
                            deviceListTemp.addAll(deviceList);
                            //设置本地的设备状态
                            mView.sendDeviceList(deviceListTemp);
                            //List<Veneer> veneerListTemp = new ArrayList<>();
                            //设置单板升级中的状态
                            veneer.setProgress(progress);
                            veneerList.set(i,veneer);
                            veneerListTemp.addAll(veneerList);
                            mView.sendVeneerList(veneerListTemp);
                        }
                    }
                }else if(status == StatusUpgrade.FAIL.getCode()){
                    IDLog.d(TAG, "showVeneerStatus: 升级失败" + success);
                    // 处理升级失败 ， 更新单板状态 ，更新设备状态
                    setDeviceStatus(deviceList, deviceListTemp,
                            veneer,veneerList,veneerListTemp,
                    i,mac,0);
                }
            }
        }
    }

    /**
     * 设置设备升级设备 将单板设置为可以升级状态
     * @param deviceList
     * @param deviceListTemp
     * @param veneer
     * @param veneerList
     * @param veneerListTemp
     * @param i
     * @param mac
     * @param progress
     */
    private void setDeviceStatus(List<Device> deviceList,List<Device> deviceListTemp,
                                 Veneer veneer,List<Veneer> veneerList,List<Veneer> veneerListTemp,
                                 int i,String mac,int progress) {
        IDLog.d(TAG, "setDeviceStatus: " + deviceList.toString());
        for(int j = 0; j < deviceList.size();j++){
            Device device = deviceList.get(j);
            if(device.getMac().equals(mac)){
                device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                int failCout = device.getFailCount();
                //升级失败次数加+1
                device.setFailCount(++failCout);
                device.setIpPort("");
                //超过三次才将这个设备
                if(failCout >= 3){
                    device.setUpdateStatus(StatusUpgrade.FAIL.getCode());
                }
                deviceList.set(j,device);
                deviceListTemp.addAll(deviceList);
                //设置本地的设备状态
                mView.sendDeviceList(deviceListTemp);
                //设置单板升级中的状态
                veneer.setProgress(progress);
                veneer.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                //设置单板升级失败次数+1
                int failVeenerCountUpdate = veneer.getFailUpdateCount();
                veneer.setFailUpdateCount(++failVeenerCountUpdate);
                //todo 单板升级失败次数
                /*if(veneer.getFailCount() >= 3){
                    veneer.setUpdateStatus(StatusUpgrade.FAIL.getCode());
                }*/
                veneerList.set(i,veneer);

                veneerListTemp.addAll(veneerList);
                mView.sendVeneerList(veneerListTemp);
                //重新开启任务升级
                startTask(mView.getDeviceList(),mView.getVeneerList());
            }
        }
    }


    /**
     * 根据ip获取设备列表
     */
    private void getDeviceListByIp(List<Veneer> veneerList) {
        if(veneerList == null)
            return;
        //清空之前的设备
        if(mDeviceList != null){
            mDeviceList.clear();
        }
        //获取有效的单板数
        mEffectCountVeneer = getEffectVeneerCount(veneerList);

        OkhttpUtil okhttpUtil = OkhttpUtil.getInstance();
        for (int i = 0; i < veneerList.size(); i++) {
            String ip = veneerList.get(i).getIp();
            if (TextUtils.isEmpty(ip)) {
                return;
            }
            String url = ApiConstant.URL_HEAD + veneerList.get(i).getIpPort()+"/"+ ApiConstant.METHOD_DEVICE_LIST;
            mView.showLoadingDialog();
            mCountVeneerScance = 0;
            okhttpUtil.getSyn(url, new OkhttpUtil.OkhttpCallback() {
                @Override
                public void onSuccess(String success) {
                    IDLog.d(TAG, "onSuccess: 扫描次数" + mCountVeneerScance +"单板数量"+ mEffectCountVeneer);

                    AppExecutors.globalAppExecutors().mainThread().execute(() ->
                            saveDeviceList(success));
                }

                @Override
                public void onFailed(String message) {
                    //扫描的次数大于单板的次数
                    //记录失败次数之后更新单板状态
                    AppExecutors.globalAppExecutors().mainThread().execute(() -> hideLoading());
                    AppExecutors.globalAppExecutors().mainThread().execute(() -> updateVeneer(message));
                }
            });
        }
    }


    /**
     * 获取有效的连接单板数
     * @param veneerList
     * @return
     */
    private int getEffectVeneerCount(List<Veneer> veneerList) {
        int effectCount = veneerList.size();
        for (int i = 0;i < veneerList.size();i++){
            Veneer veneer = veneerList.get(i);
            if(veneer.getFailConnectCount() >= Constant.CONNECT_FAIL_COUNT){
                effectCount--;
            }
        }
        return effectCount;
    }

    /**
     * 关闭loading
     */
    private void hideLoading() {
        mCountVeneerScance++;
        if(mCountVeneerScance >= mEffectCountVeneer){
            mView.hideLoadingDialog();
        }
    }

    /**
     * 更新单板状态
     * @param message
     */
    private void updateVeneer(String message) {
        IDLog.d(TAG, "updateVeneer: " + message);
        try {
            if(TextUtils.isEmpty(message))
                return;
            JSONObject jsonObject = new JSONObject(message);
            String errCode = jsonObject.getString("errcode");
            //请求失败
            if(Integer.parseInt(errCode) == Status.REQUEST_ERROR.getRequestStatus()){
                String errMsg = jsonObject.getString("errmsg");
                String ip = jsonObject.getString("ip");
                String ipPort = jsonObject.getString("ipPort");
                List<Veneer> veneerList = mView.getVeneerList();
                List<Veneer> veneerTemp = new ArrayList<>();
                List<Device> deviceList = mView.getDeviceList();
                List<Device> deviceListTemp = new ArrayList<>();
                for(int i = 0;i < veneerList.size();i++){
                    Veneer veneer = veneerList.get(i);
                    if(veneer.getIpPort().equals(ipPort)){
                        int failCount = veneer.getFailConnectCount();
                        veneer.setFailConnectCount(Constant.CONNECT_FAIL_COUNT);
                        //超过三次更新状态 todo 重新下发开启任务
                        if(veneer.getFailConnectCount() >= 3){
                            veneer.setUpdateStatus(StatusUpgrade.FAIL.getCode());
                        }
                        IDLog.d(TAG, "updateVeneer: " + veneer.getFailConnectCount());
                        veneerList.set(i,veneer);
                        veneerTemp.addAll(veneerList);
                        //更新连接数
                        mView.sendVeneerList(veneerTemp);
                    }
                }
                //在之前版本之后加的单板挂掉之后将设备重新至为等待升级的状态
                for(int j = 0;j < deviceList.size(); j++ ){
                    if(!TextUtils.isEmpty(deviceList.get(j).getIpPort())){
                        if(deviceList.get(j).getIpPort().equals(ip)){
                            Device device = deviceList.get(j);
                            device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                            deviceList.set(j,device);
                            deviceListTemp.addAll(deviceList);
                            mView.sendDeviceList(deviceListTemp);
                        }
                    }
                }
            }else if(Integer.parseInt(errCode) == Status.REQUEST_ERROR_API.getRequestStatus()){
                //todo 访问超时
                String errMsg = jsonObject.getString("errmsg");
                String ip = jsonObject.getString("ip");
                List<Veneer> veneerList = mView.getVeneerList();
                List<Veneer> veneerTemp = new ArrayList<>();
                for(int i = 0;i < veneerList.size();i++){
                    Veneer veneer = veneerList.get(i);
                    if(veneer.getIpPort().contains(ip)){
                        int failUpdateCount = veneer.getFailUpdateCount();
                        veneer.setFailUpdateCount(++failUpdateCount);
                        //请求失败
                        if(veneer.getFailUpdateCount() > Constant.REQUEST_FAIL_COUNT){
                            veneer.setUpdateStatus(StatusUpgrade.FAIL.getCode());
                        }
                        IDLog.d(TAG, "updateVeneer: " + veneer.getFailConnectCount());
                        veneerList.set(i,veneer);
                        veneerTemp.addAll(veneerList);
                        //更新连接数
                        mView.sendVeneerList(veneerTemp);
                    }
                }
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 保存设备列表
     * @param success
     */
    private void saveDeviceList(String success) {
        //保存设备列表
        mCountVeneerScance++;
        try {
            Gson gson = new Gson();
            JSONObject jsonObject = new JSONObject(success);
            String code = jsonObject.getString("errcode");
            String device = jsonObject.optString("devices");
            if(!TextUtils.isEmpty(device)){
                List<Device> deviceList = gson.fromJson(device, new TypeToken<List<Device>>() {
                }.getType());
                if(mDeviceList == null){
                    mDeviceList = new ArrayList<>();
                }
                mDeviceList.addAll(deviceList);
            }
            if(mCountVeneerScance >= mEffectCountVeneer){
                //去重
                removeDeviceDulicate(mDeviceList);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    /**
     * 去掉重复的检测到的设备
     * @param deviceList
     */
    private void removeDeviceDulicate(List<Device> deviceList) {
        Set<Device> s = new TreeSet<Device>(new Comparator<Device>() {

            @Override
            public int compare(Device o1, Device o2) {
                return o1.getMac().compareTo(o2.getMac());
            }
        });
        s.addAll(deviceList);
        deviceList = new ArrayList<Device>(s);
        mDeviceList = new ArrayList<>();
        mDeviceList.addAll(deviceList);
        //1、判断设备设备的id 和版本号是否一致 如果是则认为升级成功否则都是等待升级状态
        setSearchDeviceStatus(mDeviceList);

        
        for(Device device : mDeviceList){
            IDLog.d(TAG, "removeDeviceDulicate: " + device.toString());
        }
        //显示已发现设备
        showDeviceCount(mDeviceList.size());
        //设置现在已连接的设备数量和状态
        // todo 比较版本号相同版本号就当成升级完成 如果输入的版本
        //boolean isCanUpgrade = getDeviceVersion(mDeviceList);
        IDLog.d(TAG, "removeDeviceDulicate: " + mDeviceList.size());
        mView.sendDeviceList(mDeviceList);
        //关闭ip
        WaitingDialog.hideDialog();
        startTask(mDeviceList,mView.getVeneerList());

    }

    /**
     * 获得搜索设备的状态
     * @param mDeviceList
     */
    private void setSearchDeviceStatus(List<Device> mDeviceList) {
        List<Device> deviceList = new ArrayList<>();
        for(int i = 0;i < mDeviceList.size();i++){
            Device device = mDeviceList.get(i);
            String deviceId = mView.getDeviceId();
            // 判断是否升级成功 判断类型
            switch (mTaskName){
                case Constant.TASK_NAME_NORDIC:
                    device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    // todo 输入的设备id 和 版本号与搜索到的一致则认为是升级成功的否则都只为等待升级
                   /* if(Integer.parseInt(deviceId) == device.getDeviceId()
                            && mNordicConfig.getFirewareNormalVersion()
                            .equals(String.valueOf(device.getVersion()))){
                        device.setUpdateStatus(StatusUpgrade.COMPLETE.getCode());
                        IDLog.d(TAG, "setSearchDeviceStatus: " +device.toString());
                    }else {*/
                        device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    //}
                    mDeviceList.set(i,device);
                    break;
                case Constant.TASK_NAME_REALTK:
                    deviceId = mView.getDeviceId();
                    device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    break;
                case Constant.TASK_NAME_TWO_TO_ONE:
                    deviceId = mView.getDeviceId();
                    device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    //todo 之后只比较bootloader 版本 字库文件和最新固件
                    if(Integer.parseInt(deviceId) == device.getDeviceId()
                            && mTwoToOneConfig.getBootloaderVersion()
                            .equals(device.getBootload_version())
                            && mFourToOneConfig.getFontVersion()
                            .equals(device.getFlash_bin_version())){
                        device.setUpdateStatus(StatusUpgrade.COMPLETE.getCode());
                        IDLog.d(TAG, "removeDeviceDulicate: " +device.toString());
                    }else {
                        device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    }
                    break;
                case Constant.TASK_NAME_THREE_TO_ONE:
                    deviceId = mView.getDeviceId();
                    device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    //todo 之后只比较bootloader 版本 字库文件和最新固件
                    if(Integer.parseInt(deviceId) == device.getDeviceId()
                            && mThreeToOneConfig.getFirewareSpecialVersion()
                            .equals(device.getSpecial_version())
                            && mThreeToOneConfig.getFontVersion()
                            .equals(device.getFlash_bin_version())
                            && mThreeToOneConfig.getFirewareNewVersion()
                            .equals(device.getInternal_version())){
                        device.setUpdateStatus(StatusUpgrade.COMPLETE.getCode());
                        IDLog.d(TAG, "removeDeviceDulicate: " +device.toString());
                    }else {
                        device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    }
                    break;
                case Constant.TASK_NAME_FOUR_TO_ONE:

                    deviceId = mView.getDeviceId();
                    device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    //todo 之后只比较bootloader 版本 字库文件和最新固件
                    if(Integer.parseInt(deviceId) == device.getDeviceId()
                            && mFourToOneConfig.getBootloaderVersion()
                            .equals(device.getBootload_version())
                            && mFourToOneConfig.getFontVersion()
                            .equals(device.getFlash_bin_version())
                            && mFourToOneConfig.getFirewareNewVersion()
                            .equals(device.getInternal_version())){
                        device.setUpdateStatus(StatusUpgrade.COMPLETE.getCode());
                        IDLog.d(TAG, "removeDeviceDulicate: " +device.toString());
                    }else {
                        device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    }
                    break;
                case Constant.TASK_NAME_FONT:
                    deviceId = mView.getDeviceId();
                    device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    //todo 之后只比较bootloader 版本 字库文件和最新固件
                    if(Integer.parseInt(deviceId) == device.getDeviceId()
                            && mFontConfig.getFontVersion()
                            .equals(device.getFlash_bin_version())
                            && mFontConfig.getFirewareNewVersion()
                            .equals(device.getInternal_version())){
                        device.setUpdateStatus(StatusUpgrade.COMPLETE.getCode());
                        IDLog.d(TAG, "removeDeviceDulicate: " +device.toString());
                    }else {
                        device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    }
                    break;
                case Constant.TASK_NAME_FONT_B:
                    deviceId = mView.getDeviceId();
                    device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    //todo 之后只比较bootloader 版本 字库文件和最新固件
                    if(Integer.parseInt(deviceId) == device.getDeviceId()
                            && mFontBConfig.getBootloaderVersion()
                            .equals(device.getBootload_version())
                            && mFontBConfig.getFontVersion()
                            .equals(device.getFlash_bin_version())
                            && mFontBConfig.getFirewareNewVersion()
                            .equals(device.getInternal_version())){
                        device.setUpdateStatus(StatusUpgrade.COMPLETE.getCode());
                        IDLog.d(TAG, "removeDeviceDulicate: " +device.toString());
                    }else {
                        device.setUpdateStatus(StatusUpgrade.WAITING.getCode());
                    }
                    break;
            }

        }
        deviceList.addAll(mDeviceList);
        mView.sendDeviceList(deviceList);
    }


    /**
     * 开始分配设备给ip
     * @param mDeviceList
     */
    private void startTask(List<Device> mDeviceList,List<Veneer> veneerList) {
        //是否需要升级 todo 区分Nordic 还是四合一升级等
        mView.showSearchSuccess(false);
        if(mDeviceList.size() == 0){
            ToastUtils.show("未扫描到设备");
            return;
        }
        boolean isComplete = true;
        for(int i = 0;i < mDeviceList.size(); i++){
            Device device = mDeviceList.get(i);
            IDLog.d(TAG, "startTask: " + device.toString());
            //等待升级的设备
            for(int j= 0;j < veneerList.size();j++){
                Veneer veneer = veneerList.get(j);
                IDLog.d(TAG, "startTask: " + veneer.toString() + ","+mTaskName
                        +","+device.getVersion() +",");
                if(veneer.getUpdateStatus() == StatusUpgrade.WAITING.getCode()
                        && device.getUpdateStatus() == StatusUpgrade.WAITING.getCode()){

                    startTaskByTaskName(veneer,device,veneerList,j,i);
                    isComplete = false;
                    //升级中
                    mStatusUpgradeTask = StatusUpgradeTask.UPGRADE.getCode();
                    break;
                }
            }
        }
        if(isComplete == true){
            IDLog.d(TAG, "startTask: " + isComplete);
            //只有等所有的设备升级完成才更新数据
            for(Device device : mDeviceList){
                //如果还有准备需要升级的设备则返回
                if(device.getUpdateStatus() == StatusUpgrade.WAITING.getCode()
                        || device.getUpdateStatus() == StatusUpgrade.UPGRADE.getCode() ){
                    return;
                }
            }
            mView.stopTimer();
            mView.showProgress(false);
            //升级结束
            mStatusUpgradeTask = StatusUpgradeTask.WAITING.getCode();
            mView.showMessage(ResourceUtil.getString(R.string.task_update_complete));
            mView.setTextBtnStartTask(ResourceUtil.getString(R.string.task_start));
            showEndTaskName();
            mView.showSearchSuccess(true);
            showTaskTTS();
            //升级结束时候发起查找亮屏的命令
            searchTask(mView.getVeneerList(),mView.getDeviceList());
        }
    }

    /**
     * 显示不同类型的任务名称
     */
    private void showEndTaskName() {
        switch (mTaskName){
            case Constant.TASK_NAME_NORDIC:
                mView.setTaskName(ResourceUtil.getString(R.string.upload_type_nordic_over));
                break;
            case Constant.TASK_NAME_FOUR_TO_ONE:
                mView.setTaskName(ResourceUtil.getString(R.string.upload_type_four_to_one_over));
                break;
            case Constant.TASK_NAME_REALTK:
                mView.setTaskName(ResourceUtil.getString(R.string.upload_type_realtk_over));
                break;
            case Constant.TASK_NAME_FONT:
                mView.setTaskName(ResourceUtil.getString(R.string.upload_type_font_over));
                break;
            case Constant.TASK_NAME_TWO_TO_ONE:
                mView.setTaskName(ResourceUtil.getString(R.string.upload_type_two_to_one_over));
                break;
            case Constant.TASK_NAME_THREE_TO_ONE:
                mView.setTaskName(ResourceUtil.getString(R.string.upload_type_three_to_one_over));
                break;
            case Constant.TASK_NAME_FONT_B:
                mView.setTaskName(ResourceUtil.getString(R.string.upload_type_b_font_over));
                break;
        }

    }

    /**
     * 通过任务类型启动升级任务
     * @param veneer
     * @param device
     * @param veneerList
     * @param j
     * @param i
     */
    private void startTaskByTaskName(Veneer veneer,Device device,List<Veneer> veneerList,int j,int i) {
        if(veneer.getUpdateStatus() == StatusUpgrade.WAITING.getCode()
                && device.getUpdateStatus() == StatusUpgrade.WAITING.getCode()){
            veneer.setUpdateStatus(StatusUpgrade.UPGRADE.getCode());
            veneer.setProgress(0);
            veneerList.set(j,veneer);
            device.setUpdateStatus(StatusUpgrade.UPGRADE.getCode());
            mDeviceList.set(i,device);
            //刷新设备信息
            showDeviceList(mDeviceList);
            //调用升级接口去升级
            toStartUpgrade(veneer.getIpPort(),device.getMac(),mTaskName);

            //开启定时器
            mView.startTimer();
            mView.showProgress(true);
            mView.setTextBtnStartTask(ResourceUtil.getString(R.string.task_cancel));
            // 显示升级的设备
            IDLog.d(TAG, "startTask: "+ "设备"+i+"单板"+j);
        }
    }

    /**
     * 显示语音播报的内容
     */
    private void showTaskTTS() {
        UploadConfig uploadConfig = mUploadConfigPrefence.getUploadConfig();
        switch (uploadConfig.getTaskName()){
            case Constant.TASK_NAME_NORDIC:
                mView.showTextToTTS(ResourceUtil.getString(R.string.nordic_update_success));
                break;
            case Constant.TASK_NAME_FOUR_TO_ONE:
                mView.showTextToTTS(ResourceUtil.getString(R.string.four_to_one_update_success));
                break;
            case Constant.TASK_NAME_REALTK:
                mView.showTextToTTS(ResourceUtil.getString(R.string.realtk_update_success));
                break;
            case Constant.TASK_NAME_TWO_TO_ONE:
                mView.showTextToTTS(ResourceUtil.getString(R.string.two_to_one_update_success));
                break;
            case Constant.TASK_NAME_THREE_TO_ONE:
                mView.showTextToTTS(ResourceUtil.getString(R.string.three_to_one_udpate_success));
                break;
            case Constant.TASK_NAME_FONT:
                mView.showTextToTTS(ResourceUtil.getString(R.string.font_update_success));
                break;
            case Constant.TASK_NAME_FONT_B:
                mView.showTextToTTS(ResourceUtil.getString(R.string.font_b_update_success));
                break;
        }
    }

    /**
     * 显示设备信息
     * @param mDeviceList
     */
    @Override
    public void showDeviceList(List<Device> mDeviceList) {
        for(Device device : mDeviceList){
            IDLog.d(TAG, "showDeviceList: " + device.toString());
        }
        int mUpgradeCount = 0;
        int mSuccessCount = 0;
        int mFailCount = 0;
        for(int i = 0; i < mDeviceList.size();i++){
            Device device = mDeviceList.get(i);
            if(device.getUpdateStatus() == StatusUpgrade.UPGRADE.getCode()){
                //升级中
                mUpgradeCount++;
            }else if(device.getUpdateStatus() == StatusUpgrade.COMPLETE.getCode()){
                mSuccessCount++;
            }else if(device.getUpdateStatus() == StatusUpgrade.FAIL.getCode()){
                mFailCount++;
            }
        }
        mView.setUpgradeCount(mUpgradeCount);
        mView.setSuccessCount(mSuccessCount);
        mView.setFailCount(mFailCount);

    }

    /**
     * 调用升级节后
     * @param ipPort
     * @param mac
     */
    private void toStartUpgrade(String ipPort, String mac,String taskName) {
        OkhttpUtil okhttpUtil = OkhttpUtil.getInstance();
        StringBuffer sb = new StringBuffer();
        sb.append(ApiConstant.URL_HEAD);
        sb.append(ipPort);
        sb.append("/");
        sb.append(ApiConstant.METHOD_TASK_START);
        sb.append("?");
        sb.append("mac=");
        sb.append(mac);
        sb.append("&");
        sb.append("taskName=");
        sb.append(taskName);
        String url = sb.toString();
        IDLog.d(TAG, "toStartUpgrade: " +url);
        okhttpUtil.getSyn(url, new OkhttpUtil.OkhttpCallback() {
            @Override
            public void onSuccess(String success) {
                //设置设备ip为升级中，如果返回false 直接将单板设置为 false
                //mView.sendDeviceList(deviceList);
                //todo 设置升级的ip 和端口的状态
                AppExecutors.globalAppExecutors().mainThread().execute(() -> setVeneerStart(success));
            }

            @Override
            public void onFailed(String message) {
                //超时之后更新单板的状态
                AppExecutors.globalAppExecutors().mainThread().execute(() -> updateVeneer(message));

            }
        });
    }

    /**
     * 如果不能升级直接设置单板状态为断开状态
     * @param success
     */
    private void setVeneerStart(String success) {
        IDLog.d(TAG, "setVeneerFail: " + success);
        try {
            JSONObject jsonObject = new JSONObject(success);
            String ip = jsonObject.getString("ip");
            boolean isUpgrade = jsonObject.getBoolean("isUpgrade");
            String mac = jsonObject.getString("mac");
            String ipPort = jsonObject.getString("ipPort");
            List<Veneer> veneerList = mView.getVeneerList();
            List<Veneer> veneerListTemp = new ArrayList<>();
            List<Device> deviceList = mView.getDeviceList();
            List<Device> deviceListTemp = new ArrayList<>();
            if(!isUpgrade){
                for(int i = 0;i < veneerList.size();i++){
                    //如果设备不能升级直接返回设备失败
                    Veneer veneer = veneerList.get(i);
                    if(veneer.getIpPort().equals(ipPort)){
                        veneer.setFailConnectCount(3);
                        veneer.setUpdateStatus(StatusUpgrade.FAIL.getCode());
                        veneerList.set(i,veneer);
                        veneerListTemp.addAll(veneerList);
                        mView.sendVeneerList(veneerListTemp);
                        startTask(mView.getDeviceList(),mView.getVeneerList());
                    }
                }
            }else {
                for(int i = 0;i < deviceList.size();i++){
                    // 考虑是不是单板和设备做一个临时绑定的关系
                    // 如果单板可以升级则和设备绑定 单板升级成功或升级失败解除绑定
                    Device device = deviceList.get(i);
                    if(device.getMac().equals(mac)){
                        device.setIpPort(ipPort);
                        deviceList.set(i,device);
                        deviceListTemp.addAll(deviceList);
                        mView.sendDeviceList(deviceListTemp);
                    }
                }
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 显示发现设备数量
     * @param size
     */
    private void showDeviceCount(int size) {
        mView.sendDeviceCount(size);
        if(size == 0){
            //设置设备的数量
            mView.setDeviceCount(size);
            mView.setDeviceCountColor(ResourceUtil.getResources().getColor(R.color.com_color_red));
        }else {
            mView.setDeviceCount(size);
        }

    }
}
